package io.xxx.omni.sync.impl

import com.dangdang.openplatform.openapi.sdk.BaseResponse
import com.dangdang.openplatform.openapi.sdk.Request
import com.dangdang.openplatform.openapi.sdk.SdkClient
import com.dangdang.openplatform.openapi.sdk.request.order.OrderCancelApplyDetailsGetRequest
import com.dangdang.openplatform.openapi.sdk.request.order.OrderDetailsGetRequest
import com.dangdang.openplatform.openapi.sdk.request.order.OrdersListGetRequest
import com.dangdang.openplatform.openapi.sdk.requestmodel.order.OrderCancelDetails
import com.dangdang.openplatform.openapi.sdk.requestmodel.order.OrderDetailsGet
import com.dangdang.openplatform.openapi.sdk.requestmodel.order.OrderListGet
import com.dangdang.openplatform.openapi.sdk.response.order.OrderCancelApplyDetailsGetResponse
import com.dangdang.openplatform.openapi.sdk.response.order.OrdersListGetResponse
import io.xxx.omni.sync.Document
import io.xxx.omni.sync.PagePorter
import io.xxx.omni.sync.Store
import io.xxx.omni.util.dateTimeFormatter
import io.xxx.omni.util.toJSONObject
import io.xxx.omni.util.toLocalDateTime
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
import java.time.LocalDateTime
import kotlin.streams.toList

/**
 * 当当
 */
abstract class DdPorter<R : BaseResponse> : PagePorter() {

    override val platformCode = "dangdang"

    protected fun getResponse(store: Store, startTime: LocalDateTime, endTime: LocalDateTime, pageNo: Long = 1): R {
        var client = container["ddClient"]
        if (client == null) {
            client = SdkClient(store.appKey, store.appSecret, store.accessToken, "2.0")
            container["ddClient"] = client
        }
        val request = buildRequest(store, startTime, endTime, pageNo)
        val response = (client as SdkClient).excute(request)
        if (!response.isSuccess) {
            val msg = "接口[method: ${request.method}]异常: ${response.invokeMsg}"
            log.error(msg)
            throwException(request.method, response.invokeCode, response.invokeMsg)
        }
        return response
    }

    protected abstract fun buildRequest(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        pageNo: Long
    ): Request<R>

    companion object {
        private val log = LoggerFactory.getLogger(DdPorter::class.java)
    }
}

@Component
class DdTradePorter : DdPorter<OrdersListGetResponse>() {

    override val jobId = 1

    override fun getCount(store: Store, startTime: LocalDateTime, endTime: LocalDateTime, parameter: Any?): Long? {
        val response = getResponse(store, startTime, endTime)
        return response.totalInfo.orderCount.toLong()
    }

    override fun getData(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Long,
    ): List<Document>? {
        val response = getResponse(store, startTime, endTime, pageNo)
        val client = container["ddClient"] as SdkClient
        return response.orderList.parallelStream().map {
            val request = OrderDetailsGetRequest()
            val detailsGet = OrderDetailsGet()
            detailsGet.o = it.orderID.toString()
            detailsGet.outerOrderID = it.outerOrderID
            request.orderDetailsGet = detailsGet
            val detail = client.excute(request)
            Document(detail.orderID.toString(), detail.toJSONObject(), detail.lastModifyTime.toLocalDateTime())
        }.toList()
    }

    override fun buildRequest(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        pageNo: Long
    ): OrdersListGetRequest {
        val request = OrdersListGetRequest()
        val get = OrderListGet()
        get.os = "9999"
        get.p = pageNo.toInt()
        get.pageSize = pageSize
        get.lastModifyTime_start = startTime.format(dateTimeFormatter)
        get.lastModifyTime_end = endTime.format(dateTimeFormatter)
        request.orderListGet = get
        return request
    }
}

@Component
class DdRefundPorter : DdPorter<OrderCancelApplyDetailsGetResponse>() {

    override val jobId = 2

    override fun getCount(store: Store, startTime: LocalDateTime, endTime: LocalDateTime, parameter: Any?): Long? {
        val response = getResponse(store, startTime, endTime)
        return response.orderCancelApplyRemote.size.toLong()
    }

    override fun getData(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        parameter: Any?,
        pageNo: Long,
    ): List<Document>? {
        val response = getResponse(store, startTime, endTime, pageNo)
        return response.orderCancelApplyRemote.map {
            Document(
                it.applyId.toString(),
                it.orderId.toString(),
                it.toJSONObject(),
                it.lastChangeDate.toLocalDateTime()
            )
        }
    }

    override fun buildRequest(
        store: Store,
        startTime: LocalDateTime,
        endTime: LocalDateTime,
        pageNo: Long
    ): OrderCancelApplyDetailsGetRequest {
        val request = OrderCancelApplyDetailsGetRequest()
        val details = OrderCancelDetails()
        details.creationDateBegin = startTime.format(dateTimeFormatter)
        details.creationDateEnd = endTime.format(dateTimeFormatter)
        request.orderCancelDetails = details
        return request
    }
}